package yang.java8.lambda3;

import javafx.scene.image.Image;
import javafx.scene.image.WritableImage;
import javafx.scene.paint.Color;

import java.awt.image.WritableRenderedImage;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.IntConsumer;
import java.util.function.UnaryOperator;

import yang.java8.util.Util;

public class Study3 {

	public static void main(String[] args) {
//		Section7();
	}
	
	public static void repeat(int n, IntConsumer action) {
		for (int i = 0; i < n; i++) {
			action.accept(i);
		}
	}
	
	public static void repeatV1(int n, Runnable runnable) {
		for (int i = 0; i < n; i++) {
			runnable.run();
		}
	}
	
	public static void Section2() {
		String[] names = new String[100];
		Arrays.sort(names, (s,t) -> Integer.compare(s.length(), t.length()));
		repeat(10, i -> System.out.println("Countdown: " + (9 - i)));
		repeatV1(10, () -> System.out.println("Hello, World!"));
		
	}
	
	public static Image transform(Image in, UnaryOperator<Color> f) {
		int width = (int) in.getWidth();
		int height = (int) in.getHeight();
		WritableImage out = new WritableImage(width, height);
		for (int x = 0; x < width; x++) {
			for (int y = 0; y < height; y++) {
				out.getPixelWriter().setColor(x, y, f.apply(in.getPixelReader().getColor(x, y)));
			}
		}
		return out;
	}
	
	public static void Section3() {
		Image image = new Image("");
		Image brightenedImage = transform(image, Color::brighter);
	}
	
	public static <T> Image transform(Image in, BiFunction<Color, T, Color> f, T factor) {
		int width = (int) in.getWidth();
		int height = (int) in.getHeight();
		WritableImage out = new WritableImage(width, height);
		for (int x = 0; x < width; x++) {
			for (int y = 0; y < height; y++) {
				out.getPixelWriter().setColor(x, y, f.apply(in.getPixelReader().getColor(x, y), factor));
			}
		}
		return out;
	}
	
	public static UnaryOperator<Color> brighten(double factor) {
		return c -> c.deriveColor(0, 1, factor, 1);
	}
	
	public static void Section4() {
		Image image = new Image("");
		Image brightenedImage = transform(image, (c, factor) -> c.deriveColor(0, 1, factor, 1), 1.2);
		brightenedImage = transform(image, brighten(1.2));
	}
	
	public static <T> UnaryOperator<T> compose(UnaryOperator<T> op1, UnaryOperator<T> op2) {
		return t -> op2.apply(op1.apply(t));
	}
	
	public static Image transformV1(Image in, Function<Color, Color> f) {
		int width = (int) in.getWidth();
		int height = (int) in.getHeight();
		WritableImage out = new WritableImage(width, height);
		for (int x = 0; x < width; x++) {
			for (int y = 0; y < height; y++) {
				out.getPixelWriter().setColor(x, y, f.apply(in.getPixelReader().getColor(x, y)));
			}
		}
		return out;
	}
	
	public static void Section5() {
		Image image = new Image("");
		Image image2 = transform(image, Color::brighter);
		Image finalImage = transform(image2, Color::grayscale);// 中间图片，效率不高
		finalImage = transform(image, compose(Color::brighter, Color::grayscale));
		finalImage = transform(image, compose(Color::brighter, Color::grayscale));
		finalImage = transformv1(image2, Color::grayscale, Color::grayscale);
		
		UnaryOperator<Color> op = Color::brighter;
		Image finalImage1 = transformV1(image, op.compose(Color::grayscale));
	}
	
	public static Image transformv1(Image in, UnaryOperator<Color>... f) {
		int width = (int) in.getWidth();
		int height = (int) in.getHeight();
		WritableImage out = new WritableImage(width, height);
		for (int x = 0; x < width; x++) {
			for (int y = 0; y < height; y++) {
				Color tmp = in.getPixelReader().getColor(x, y);
				for (UnaryOperator<Color> uo : f){
					tmp = uo.apply(tmp);
				}
				out.getPixelWriter().setColor(x, y, tmp);
			}
		}
		return out;
	}
	
	public static Color[][] parallelTransform(Color[][] in, UnaryOperator<Color> f) {
		int n = Runtime.getRuntime().availableProcessors();
		int height = in.length;
		int width = in[0].length;
		Color[][] out = new Color[height][width];
		try {
			ExecutorService pool = Executors.newCachedThreadPool();
			for (int i = 0; i < n; i++) {
				int formY = i * height / n;
				int toY = (i + 1) * height /n;
				pool.submit(() -> {
					for (int x = 0; x < width; x++) {
						for (int y = formY; y < toY && y < height; y++) {
							out[y][x] = f.apply(in[y][x]);
						}
					}
				});
			}
			pool.shutdown();
			pool.awaitTermination(1, TimeUnit.HOURS);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return out;
	}
	

}
